{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "is_executing": false
    }
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.ticker as ticker\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "import unicodedata\n",
    "import re\n",
    "import numpy as np\n",
    "import os\n",
    "import io\n",
    "import time\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [],
   "source": [
    "# Download the file\n",
    "path_to_zip = tf.keras.utils.get_file(\n",
    "    'spa-eng.zip', origin='http://storage.googleapis.com/download.tensorflow.org/data/spa-eng.zip',\n",
    "    extract=True)\n",
    "\n",
    "path_to_file = os.path.dirname(path_to_zip)+\"/spa-eng/spa.txt\"\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [],
   "source": [
    "# Converts the unicode file to ascii\n",
    "def unicode_to_ascii(s):\n",
    "    return ''.join(c for c in unicodedata.normalize('NFD', s)\n",
    "        if unicodedata.category(c) != 'Mn')\n",
    "\n",
    "\n",
    "def preprocess_sentence(w):\n",
    "    w = unicode_to_ascii(w.lower().strip())\n",
    "\n",
    "    # creating a space between a word and the punctuation following it\n",
    "    # eg: \"he is a boy.\" => \"he is a boy .\"\n",
    "    # Reference:- https://stackoverflow.com/questions/3645931/python-padding-punctuation-with-white-spaces-keeping-punctuation\n",
    "    w = re.sub(r\"([?.!,¿])\", r\" \\1 \", w)\n",
    "    w = re.sub(r'[\" \"]+', \" \", w)\n",
    "\n",
    "    # replacing everything with space except (a-z, A-Z, \".\", \"?\", \"!\", \",\")\n",
    "    w = re.sub(r\"[^a-zA-Z?.!,¿]+\", \" \", w)\n",
    "\n",
    "    w = w.rstrip().strip()\n",
    "\n",
    "    # adding a start and an end token to the sentence\n",
    "    # so that the model know when to start and stop predicting.\n",
    "    w = '<start> ' + w + ' <end>'\n",
    "    return w"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "<start> may i borrow this book ? <end>\n",
      "b'<start> \\xc2\\xbf puedo tomar prestado este libro ? <end>'\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "\n",
    "en_sentence = u\"May I borrow this book?\"\n",
    "sp_sentence = u\"¿Puedo tomar prestado este libro?\"\n",
    "print(preprocess_sentence(en_sentence))\n",
    "print(preprocess_sentence(sp_sentence).encode('utf-8'))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "def create_dataset(path, num_examples):\n",
    "    lines = io.open(path, encoding='UTF-8').read().strip().split('\\n')\n",
    "\n",
    "    word_pairs = [[preprocess_sentence(w) for w in l.split('\\t')]  for l in lines[:num_examples]]\n",
    "\n",
    "    return zip(*word_pairs)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "<start> if you want to sound like a native speaker , you must be willing to practice saying the same sentence over and over in the same way that banjo players practice the same phrase over and over until they can play it correctly and at the desired tempo . <end>\n",
      "<start> si quieres sonar como un hablante nativo , debes estar dispuesto a practicar diciendo la misma frase una y otra vez de la misma manera en que un musico de banjo practica el mismo fraseo una y otra vez hasta que lo puedan tocar correctamente y en el tiempo esperado . <end>\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "\n",
    "en, sp = create_dataset(path_to_file, None)\n",
    "print(en[-1])\n",
    "print(sp[-1])"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [],
   "source": [
    "def max_length(tensor):\n",
    "    return max(len(t) for t in tensor)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "def tokenize(lang):\n",
    "    lang_tokenizer = tf.keras.preprocessing.text.Tokenizer(\n",
    "        filters=\"\"\n",
    "    )\n",
    "    lang_tokenizer.fit_on_texts(lang)\n",
    "    tensor = lang_tokenizer.texts_to_sequences(lang)\n",
    "    tensor = tf.keras.preprocessing.sequence.pad_sequences(tensor,padding='post')\n",
    "    return tensor,lang_tokenizer\n",
    "\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "def load_dataset(path, num_examples=None):\n",
    "    # creating cleaned input, output pairs\n",
    "    targ_lang, inp_lang = create_dataset(path, num_examples)\n",
    "\n",
    "    input_tensor, inp_lang_tokenizer = tokenize(inp_lang)\n",
    "    target_tensor, targ_lang_tokenizer = tokenize(targ_lang)\n",
    "\n",
    "    return input_tensor, target_tensor, inp_lang_tokenizer, targ_lang_tokenizer\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [],
   "source": [
    "num_examples = 30000\n",
    "input_tensor,target_tensor,inp_lang,targ_lang = load_dataset(path_to_file,num_examples)\n",
    "\n",
    "max_length_targ,max_length_inp = max_length(target_tensor),max_length(input_tensor)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "24000 24000 6000 6000\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "input_tensor_train, input_tensor_val, target_tensor_train, target_tensor_val = train_test_split(input_tensor, target_tensor, test_size=0.2)\n",
    "\n",
    "# Show length\n",
    "print(len(input_tensor_train), len(target_tensor_train), len(input_tensor_val), len(target_tensor_val))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [],
   "source": [
    "def convert(lang, tensor):\n",
    "  for t in tensor:\n",
    "    if t!=0:\n",
    "      print (\"%d ----> %s\" % (t, lang.index_word[t]))\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "Input Language; index to word mapping\n",
      "1 ----> <start>\n",
      "7 ----> es\n",
      "15 ----> un\n",
      "3540 ----> salame\n",
      "3 ----> .\n",
      "2 ----> <end>\n",
      "\n",
      "Target Language; index to word mapping\n",
      "1 ----> <start>\n",
      "14 ----> he\n",
      "11 ----> s\n",
      "273 ----> stupid\n",
      "3 ----> .\n",
      "2 ----> <end>\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "\n",
    "print (\"Input Language; index to word mapping\")\n",
    "convert(inp_lang, input_tensor_train[0])\n",
    "print ()\n",
    "print (\"Target Language; index to word mapping\")\n",
    "convert(targ_lang, target_tensor_train[0])"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [],
   "source": [
    "BUFFER_SIZE = len(input_tensor_train)\n",
    "BATCH_SIZE = 64\n",
    "steps_per_epoch = len(input_tensor_train) // BATCH_SIZE\n",
    "embedding_dim = 256\n",
    "units = 1024\n",
    "vocab_inp_size = len(inp_lang.word_index) + 1\n",
    "vocab_tar_size = len(targ_lang.word_index) + 1\n",
    "\n",
    "dataset = tf.data.Dataset.from_tensor_slices((input_tensor_train,target_tensor_train)).shuffle(BUFFER_SIZE)\n",
    "dataset = dataset.batch(BATCH_SIZE,drop_remainder=True)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "(64, 16)\n",
      "(64, 11)\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "example_input_batch,example_target_batch = next(iter(dataset))\n",
    "print(example_input_batch.shape)\n",
    "print(example_target_batch.shape)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [],
   "source": [
    "class Encoder(tf.keras.Model):\n",
    "    def __init__(self,vocab_size,embedding_dim,enc_units,batch_sz):\n",
    "        super(Encoder,self).__init__()\n",
    "        self.batch_sz = batch_sz\n",
    "        self.enc_units = enc_units\n",
    "        self.embedding = tf.keras.layers.Embedding(vocab_size,embedding_dim)\n",
    "        self.gru = tf.keras.layers.GRU(self.enc_units,\n",
    "                                       return_sequences=True,\n",
    "                                       return_state=True,\n",
    "                                       recurrent_initializer='glorot_uniform')\n",
    "    \n",
    "    def call(self,x,hidden):\n",
    "        x = self.embedding(x)\n",
    "        output,state = self.gru(x,initial_state=hidden)\n",
    "        return output,state\n",
    "    \n",
    "    def initialize_hidden_state(self):\n",
    "        return tf.zeros((self.batch_sz,self.enc_units))\n",
    "\n",
    "\n",
    "        \n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "Encoder output shape: (batch size, sequence length, units) (64, 16, 1024)\n",
      "Encoder Hidden state shape: (batch size, units) (64, 1024)\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "encoder = Encoder(vocab_inp_size,embedding_dim,units,BATCH_SIZE)\n",
    "\n",
    "sample_hidden = encoder.initialize_hidden_state()\n",
    "sample_output,sample_hidden = encoder(example_input_batch,sample_hidden)\n",
    "print ('Encoder output shape: (batch size, sequence length, units) {}'.format(sample_output.shape))\n",
    "print ('Encoder Hidden state shape: (batch size, units) {}'.format(sample_hidden.shape))\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "WARNING:tensorflow:Tensor._shape is private, use Tensor.shape instead. Tensor._shape will eventually be removed.\n",
      "WARNING:tensorflow:Tensor._shape is private, use Tensor.shape instead. Tensor._shape will eventually be removed.\n",
      "WARNING:tensorflow:Tensor._shape is private, use Tensor.shape instead. Tensor._shape will eventually be removed.\n",
      "WARNING:tensorflow:Tensor._shape is private, use Tensor.shape instead. Tensor._shape will eventually be removed.\n",
      "WARNING:tensorflow:Tensor._shape is private, use Tensor.shape instead. Tensor._shape will eventually be removed.\n",
      "WARNING:tensorflow:Tensor._shape is private, use Tensor.shape instead. Tensor._shape will eventually be removed.\n",
      "WARNING:tensorflow:Tensor._shape is private, use Tensor.shape instead. Tensor._shape will eventually be removed.\n",
      "Attention result shape: (batch size, units) (64, 1024)\n",
      "Attention weights shape: (batch_size, sequence_length, 1) (64, 16, 1)\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "class BahdanauAttention(tf.keras.Model):\n",
    "    def __init__(self,units):\n",
    "        super(BahdanauAttention,self).__init__()\n",
    "        self.W1 = tf.keras.layers.Dense(units)\n",
    "        self.W2 = tf.keras.layers.Dense(units)\n",
    "        self.V = tf.keras.layers.Dense(1)\n",
    "    \n",
    "    def call(self,query,values):\n",
    "        # hidden shape == (batch_size, hidden size)\n",
    "        # hidden_with_time_axis shape == (batch_size, 1, hidden size)\n",
    "        # we are doing this to perform addition to calculate the score\n",
    "        hidden_with_time_axis = tf.expand_dims(query,1)\n",
    "        \n",
    "        # score shape == (batch_size, max_length, 1)\n",
    "        # we get 1 at the last axis because we are applying score to self.V\n",
    "        # the shape of the tensor before applying self.V is (batch_size, max_length, units)\n",
    "        score = self.V(tf.nn.tanh(\n",
    "            self.W1(values) + self.W2(hidden_with_time_axis)\n",
    "        ))\n",
    "        \n",
    "        # attention_weights shape == (batch_size, max_length, 1)\n",
    "        attention_weights = tf.nn.softmax(score,axis=1)\n",
    "        \n",
    "        # context_vector shape after sum == (batch_size, hidden_size)\n",
    "        context_vector = attention_weights * values\n",
    "        context_vector = tf.reduce_sum(context_vector,axis=1)\n",
    "        \n",
    "        return context_vector,attention_weights\n",
    "\n",
    "attention_layer = BahdanauAttention(10)\n",
    "attention_result,attention_weights = attention_layer(sample_hidden,sample_output)\n",
    "\n",
    "print(\"Attention result shape: (batch size, units) {}\".format(attention_result.shape))\n",
    "print(\"Attention weights shape: (batch_size, sequence_length, 1) {}\".format(attention_weights.shape))\n",
    "        \n",
    "        \n",
    "        "
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [],
   "source": [
    "class Decoder(tf.keras.Model):\n",
    "    def __init__(self,vocab_size,embedding_dim,dec_units,batch_sze):\n",
    "        super(Decoder,self).__init__()\n",
    "        self.batch_sz = batch_sze\n",
    "        self.dec_units = dec_units\n",
    "        self.embedding = tf.keras.layers.Embedding(vocab_size,embedding_dim)\n",
    "        self.gru = tf.keras.layers.GRU(self.dec_units,\n",
    "                                       return_sequences=True,\n",
    "                                       return_state=True,\n",
    "                                       recurrent_initializer='glorot_uniform')\n",
    "        self.fc = tf.keras.layers.Dense(vocab_size)\n",
    "        \n",
    "        self.attention = BahdanauAttention(self.dec_units)\n",
    "\n",
    "    \n",
    "    def call(self,x,hidden,enc_output):\n",
    "        # enc_output shape == (batch_size, max_length, hidden_size)\n",
    "        context_vector,attention_weights = self.attention(hidden,enc_output)\n",
    "        \n",
    "        #x shape after passing through embedding == (batch_size, 1, embedding_dim)\n",
    "        x = self.embedding(x)\n",
    "        \n",
    "        # x shape after concatenation == (batch_size, 1, embedding_dim + hidden_size)\n",
    "        x = tf.concat([tf.expand_dims(context_vector,1),x],axis=-1)\n",
    "        \n",
    "        # passing the concatenated vector to the GRU\n",
    "        output ,state = self.gru(x)\n",
    "        output = tf.reshape(output,(-1,output.shape[2]))\n",
    "        \n",
    "        x = self.fc(output)\n",
    "        return x,state,attention_weights\n",
    "        \n",
    "        \n",
    "        \n",
    "        \n",
    "        \n",
    "        \n",
    "    \n",
    "    \n",
    "        "
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [
    {
     "name": "stdout",
     "text": [
      "Decoder output shape: (batch_size, vocab size) (64, 4935)\n"
     ],
     "output_type": "stream"
    }
   ],
   "source": [
    "decoder = Decoder(vocab_tar_size, embedding_dim, units, BATCH_SIZE)\n",
    "\n",
    "sample_decoder_output, _, _ = decoder(tf.random.uniform((64, 1)),\n",
    "                                      sample_hidden, sample_output)\n",
    "\n",
    "print ('Decoder output shape: (batch_size, vocab size) {}'.format(sample_decoder_output.shape))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [],
   "source": [
    "optimizer = tf.keras.optimizers.Adam()\n",
    "loss_object = tf.keras.losses.SparseCategoricalCrossentropy(\n",
    "    from_logits=True,reduction='none'\n",
    ")\n",
    "\n",
    "def loss_function(real,pred):\n",
    "    mask = tf.math.logical_not(tf.math.equal(real,0))\n",
    "    loss_ = loss_object(real,pred)\n",
    "    \n",
    "    mask = tf.cast(mask,dtype=loss_.dtype)\n",
    "    loss_ *= mask\n",
    "    return tf.reduce_mean(loss_)\n",
    "\n",
    "    \n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [],
   "source": [
    "checkpoint_dir = 'output/training_checkpoints'\n",
    "checkpoint_prefix = os.path.join(checkpoint_dir,'ckpt')\n",
    "checkpoint = tf.train.Checkpoint(optimizer=optimizer,\n",
    "                                 encoder=encoder,\n",
    "                                 decoder=decoder)\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [],
   "source": [
    "#tf.function\n",
    "def train_step(inp,targ,enc_hidden):\n",
    "    loss = 0\n",
    "    with tf.GradientTape() as tape:\n",
    "        enc_output,enc_hidden = encoder(inp,enc_hidden)\n",
    "        dec_hidden = enc_hidden\n",
    "        dec_input = tf.expand_dims([targ_lang.word_index['<start>']] *BATCH_SIZE,1)\n",
    "        \n",
    "        for t in range(1,targ.shape[1]):\n",
    "            predictions,dec_hidden,_ = decoder(dec_input,dec_hidden,enc_output)\n",
    "            loss += loss_function(targ[:,t],predictions)\n",
    "            dec_input = tf.expand_dims[targ[:,t],1]\n",
    "    \n",
    "    batch_loss =  (loss /int(targ.shape[1]))\n",
    "    variables = encoder.trainable_variables + decoder.trainable_variables\n",
    "    \n",
    "    gradients = tape.gradient(loss,variables)\n",
    "    optimizer.apply_gradients(zip(gradients,variables))\n",
    "    return batch_loss\n",
    "            \n",
    "        \n",
    "Epochs = 5\n",
    "for epoch in range(Epochs):\n",
    "    start = time.time()\n",
    "    \n",
    "    enc_hidden = encoder.initialize_hidden_state()\n",
    "    total_loss = 0\n",
    "    for (batch,(inp,targ)) in enumerate(dataset.take(steps_per_epoch)):\n",
    "        batch_loss = train_step(inp,targ,enc_hidden)\n",
    "        total_loss += batch_loss\n",
    "        \n",
    "        if batch % 100 == 0:\n",
    "            print('Epoch {} Batch {} Loss {:.4f}'.format(epoch + 1,\n",
    "                                                     batch,\n",
    "                                                     batch_loss.numpy()))\n",
    "    \n",
    "    if (epoch +1) % 2 == 0:\n",
    "        checkpoint.save(file_prefix=checkpoint_prefix)\n",
    "    print('Epoch {} Loss {:.4f}'.format(epoch + 1,\n",
    "                                      total_loss / steps_per_epoch))\n",
    "    print('Time taken for 1 epoch {} sec\\n'.format(time.time() - start))\n",
    "    \n",
    "            "
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n",
     "is_executing": false
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "def evaluate(sentence):\n",
    "    attention_plot = np.zeros((max_length_targ,max_length_inp))\n",
    "    sentence = preprocess_sentence(sentence)\n",
    "    \n",
    "    inputs = [inp_lang.word_index[i] for i in sentence.split(\" \")]\n",
    "    inputs = tf.keras.preprocessing.sequence.pad_sequences(\n",
    "        [inputs],\n",
    "        maxlen=max_length_inp,\n",
    "        padding='post'\n",
    "    )\n",
    "    inputs = tf.convert_to_tensor(inputs)\n",
    "    result = \"\"\n",
    "    hidden = [tf.zeros((1,units))]\n",
    "    enc_out,enc_hidden = encoder(inputs,hidden)\n",
    "    \n",
    "    dec_hidden=enc_hidden\n",
    "    dec_input = tf.expand_dims([targ_lang.word_index['<start>']],0)\n",
    "    \n",
    "    for t in range(max_length_targ):\n",
    "        predictions,dec_hidden,attention_weights = decoder(dec_input,\n",
    "                                                           dec_hidden,\n",
    "                                                           enc_out)\n",
    "        predicted_id = tf.argmax(predictions[0]).numpy()\n",
    "        result += targ_lang.index_word[predicted_id] + \" \"\n",
    "        if targ_lang.index_word[predicted_id] == \"<end>\":\n",
    "            return result,sentence,attention_plot\n",
    "        dec_input = tf.expand_dims([predicted_id],0)\n",
    "    return result,sentence,attention_plot\n",
    "\n",
    "    \n",
    "    \n",
    "        \n",
    "        \n",
    "    \n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "name": "conda-env-keras-py",
   "language": "python",
   "display_name": "Python [conda env:keras]"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "source": [],
    "metadata": {
     "collapsed": false
    }
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}